<?php


namespace App\Services;


class WechatService
{
    /**
     * 微信
     * @param $message
     * @param array $request
     * @param array $response
     */
    public static function requestLog($message,$request=[],$response=[]){
        $content = [
            'request'=>is_object($request) ? object_array($request) : $request,
            'response'=>is_object($response) ? object_array($response) : $response,
        ];
        \Illuminate\Support\Facades\Log::debug($message,$content);
    }
    public static function addLog($message,$request=[],$response=[]){
        $content = [
            'request'=>is_object($request) ? object_array($request) : $request,
            'response'=>is_object($response) ? object_array($response) : $response,
        ];
        \Illuminate\Support\Facades\Log::debug($message,$content);
    }


    public static function requestLog2($message,$request=[],$response=[]){
        $content = [
            'request'=>is_object($request) ? object_array($request) : $request,
            'response'=>is_object($response) ? object_array($response) : $response,
        ];
        \Illuminate\Support\Facades\Log::debug($message,$content);
    }
    /**
     * 获取accessToken
     * @return array
     */
    public static function getAccessToken(){
        $data =  [];
        $url = config('wechat.apiUrl')."/cgi-bin/token";
        $param = [
            'appid'=>config('wechat.appId'),
            'secret'=>config('wechat.appSecret'),
            'grant_type'=>'client_credential',
        ];
        $result = http_get($url,$param);
        $result = json_decode($result,true);
        if (isset($result['errcode'])) {
            $flag =  false;
        }else{
            $flag =  true;
            $data = $result;
        }
        return ['status'=>$flag, 'message'=>$flag ? '成功' : '失败','data'=>$data];
    }

    /**
     * 小程序授权
     * @param $code
     * @return array
     */
    public static function authToken($code){
        $data =  [];
        $url = config('wechat.apiUrl')."/sns/jscode2session";
        $param = [
            'appid'=>config('wechat.appId'),
            'secret'=>config('wechat.appSecret'),
            'js_code'=>$code,
            'grant_type'=>'authorization_code',
        ];
        $result = http_get($url,$param);
        $result = json_decode($result,true);
        self::requestLog('小程序授权登录',['code'=>$code],$result);
        if (isset($result['errcode'])) {
            $flag =  false;
        }else{
            $flag =  true;
            $data = $result;
        }
        return ['status'=>$flag, 'message'=>$flag ? '成功' : '失败','data'=>$data];
    }

    /**
     * 获取手机号
     * @param $code
     * @return array
     */
    public static function getMobile($code){
        $accessToken = self::getAccessToken();
        if(!$accessToken['status']){
            $flag =  false;
        }else{
            $data =  [];
            $url = config('wechat.apiUrl')."/wxa/business/getuserphonenumber?access_token=".$accessToken['data']['access_token'];
            $param = [
                'code'=>$code,
            ];
            $result = http_post($url,json_encode($param),['Content-type: application/json;charset=UTF-8']);
            $result = json_decode($result,true);
            self::requestLog('小程序获取手机号',['code'=>$code],$result);
            //成功
            if (isset($result['errcode']) && $result['errcode'] == 0) {
                $flag =  true;
                $data = $result;
            }else{
                $flag =  false;
            }
        }
        return ['status'=>$flag, 'message'=>$flag ? '成功' : '失败','data'=>$data];
    }

    public static function get_delivery_list(){
        $accessToken = self::getAccessToken();
//        var_dump($accessToken);
        // dd($accessToken);
        $url = 'https://api.weixin.qq.com/cgi-bin/express/delivery/open_msg/get_delivery_list?access_token='.$accessToken['data']['access_token'];
//        $param = [
//            "order_key"=>['order_number_type'=>2,'transaction_id'=>$order['out_order_no']],
//            "logistics_type"=>1,
//            "delivery_mode"=>1,
//            "shipping_list"=>['tracking_no'=>$order['logistics_no'],'express_company'=>$order['address_mobile'],
//                'shipping_list'=>$order['goods_title'].$order['setmeal_title'],
//                'contact'=>['consignor_contact'=>'19357616167','receiver_contact'=>'']
//            ],
//            "payer"=>['openid'=>$order['openId']]
//        ];
        $param=[];
        $result = http_post($url,'{}');
        var_dump($result);
        return $result;
        dd($result);
        $flag=false;
        if($result){
            $flag=true;
        }

        return ['status'=>$flag, 'message'=>$flag ? '成功' : '失败','data'=> $result];
    }
    /**
     * 发货信息录入
     * @param  $order
     * @return array
     * @throws \Exception
     */
    public static function upload_shipping_info($order){
        $accessToken = self::getAccessToken();
//   dd($order);
        $url = 'https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token='.$accessToken['data']['access_token'];
        $param = [
            "order_key"=>['order_number_type'=>2,'transaction_id'=>$order['out_order_no']],
            "delivery_mode"=>1,
            "logistics_type"=>1,
            "shipping_list"=>[['tracking_no'=>$order['logistics_no'],'express_company'=>'SF',
                'item_desc'=>$order['goods_title'].$order['setmeal_title'],
                'contact'=>['consignor_contact'=>'193****6167','receiver_contact'=>substr($order['address_mobile'],0,3).'****'.substr($order['address_mobile'],-4,4)]
            ]],
            'upload_time'=>date('c',$order['create_time']),
            "payer"=>['openid'=>$order['openId']]
        ];
//   dd(json_encode($param,JSON_UNESCAPED_UNICODE));
        $result = http_post($url,json_encode($param,JSON_UNESCAPED_UNICODE));
//        dd($result);
        $flag=false;
        if($result){
            $flag=true;
        }

        return ['status'=>$flag, 'message'=>$flag ? '成功' : '失败','data'=> $result];
    }

    public static function upload_shipping_info_lease($order,$leaseId){
        $accessToken = self::getAccessToken();
//   dd($order);
        $url = 'https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token='.$accessToken['data']['access_token'];
        $param = [
            "order_key"=>['order_number_type'=>2,'transaction_id'=>$order['out_order_no']],
            "delivery_mode"=>1,
            "logistics_type"=>3,
            "shipping_list"=>[[
                'item_desc'=>$order['goods_title'].' ，'.$order['setmeal_title'].' ，第'.$leaseId.'期的租金',
            ]],
            'upload_time'=>date('c',$order['create_time']),
            "payer"=>['openid'=>$order['openId']]
        ];
        $result = http_post($url,json_encode($param,JSON_UNESCAPED_UNICODE));
//        dd($result);
        $flag=false;
        if($result){
            $flag=true;
        }

        self::requestLog('虚拟发货',$param,$result);

        return ['status'=>$flag, 'message'=>$flag ? '成功' : '失败','data'=> $result];
    }


    //订单列表
    public static function get_order_list(){
        $accessToken = self::getAccessToken();
        $url = 'https://api.weixin.qq.com/wxa/sec/order/get_order_list?access_token='.$accessToken['data']['access_token'];
        $param = [
            "order_state"=>1,
        ];
        $result = http_post($url,json_encode($param,JSON_UNESCAPED_UNICODE));
        $flag=false;
        if($result){
            $flag=true;
        }

        self::requestLog('查询订单列表',$param,$result);

        return ['status'=>$flag, 'message'=>$flag ? '成功' : '失败','data'=> $result];
    }

    /**
     * 个人生成二维码
     * @param  $goods_id
     * @param  $sale_user_id 下单分销商ID
     * @return array
     * @throws \Exception
     */
    public static function createUserQrCode($sale_user_id){
        $accessToken = self::getAccessToken();
        // dd($accessToken);
        $url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.$accessToken['data']['access_token'];
        $param = [
            "path"=>"pages/index/index",
            "scene"=>'saleuserid='.$sale_user_id
        ];

        $result = http_post($url,json_encode($param));
        $flag=false;
        if($result){
            $flag=true;
        }

        return ['status'=>$flag, 'message'=>$flag ? '成功' : '失败','data'=> $result];
    }

    /**
     * 微信支付
     * @param $code
     * @return array
     */
    public static function pay($openid,$order,$leaseId){
        $res=self::unifiedorder($openid,$order,$leaseId);
            $res['timeStamp']=time();
        $sign=array(
           'appId'=>config('wechat.appId'),
          'timeStamp'=>$res['timeStamp'],
          'nonceStr'=>$res['nonce_str'],
          'package'=>"prepay_id=".$res['prepay_id'],
          'signType'=>'MD5',
        );
       $res['paySign']=self::MakeSign($sign);
        return $res;
    }
    /**
     * 微信获取link链接
     * @param $code
     * @return array
     */
    public static function getLinkUrl($sale_user_id){
        $accessToken = self::getAccessToken();
        // dd($accessToken);
        $url = 'https://api.weixin.qq.com/wxa/generate_urllink?access_token='.$accessToken['data']['access_token'];

        $param = [
            "path"=>"/pages/index/index",
            "query"=>"saleuserid=".$sale_user_id,
            "is_expire"=>true,
            "expire_type"=>1,
            "expire_interval"=>30,
            "env_version"=>"release"
        ];

        $result = http_post($url,json_encode($param),['Content-type: application/json;charset=UTF-8']);
        $result = json_decode($result,true);

       return $result;

    }
    /**
     * 微信获取scheme链接
     * @param $code
     * @return array
     */
    public static function getSchemeUrl(){
        $accessToken = self::getAccessToken();
        // dd($accessToken);
        $url = 'https://api.weixin.qq.com/wxa/generatescheme?access_token='.$accessToken['data']['access_token'];
        $param = [
            'jump_wxa'=>[
                "path"=>"/pagesB/bankCard/bankCard",
                "query"=>"",
                "env_version"=>"release"
            ],
            "is_expire"=>true,
            "expire_type"=>1,
            "expire_interval"=>30
        ];

        $result = http_post($url,json_encode($param),['Content-type: application/json;charset=UTF-8']);
        $result = json_decode($result,true);

       return $result;

    }
    /**
     * 微信支付
     * @param $code
     * @return array
     */
    public static function unifiedorder($openid,$order,$leaseId){
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $data = [
            'appid'             => config('wechat.appId'),
            'mch_id'            => config('wechat.mchId'),
            'nonce_str'         => md5(uniqid()),
            'sign_type'         => 'MD5',
            'body'              =>  $order['goods_title'],  //商品描述
            'attach'            => $order['id'].','.implode(',',$leaseId),
            'out_trade_no'      => $order['trade_no'].mt_rand(1000,9999),//订单号
            'fee_type'          => 'CNY',
            'total_fee'         => bcmul($order['total_fee'],100),  //总金额
            'spbill_create_ip'  => $_SERVER['REMOTE_ADDR'],
            'notify_url'        => config('alipay.callbackDomain').'/Wechat/Notice/wechatPayNotify',
            'trade_type'        => 'JSAPI',
            'openid'            => $openid
        ];
        // 获取签名
       $sign = self::MakeSign($data);
       $data['sign'] = $sign;
    //   dd($data);
       $xml = self::ToXml($data);
    //   dd($xml);
       // 提交获取数据
       $res = self::postXmlCurl($xml,$url,false);
    //   dd($res);
       $result = self::FromXml($res);
       return $result;

    }

    /**
     * 微信支付
     * @param $code
     * @return array
     */
    public static function unifiedorderPart($openid,$order,$leaseId){
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $data = [
            'appid'             => config('wechat.appId'),
            'mch_id'            => config('wechat.mchId'),
            'nonce_str'         => md5(uniqid()),
            'sign_type'         => 'MD5',
            'body'              =>  $order['orderDescribe'],  //商品描述
            'attach'            =>  $leaseId,
            'out_trade_no'      => $order['out_trade_no'],//订单号
            'fee_type'          => 'CNY',
            'total_fee'         => bcmul($order['total_fee'],100),  //总金额
            'spbill_create_ip'  => $_SERVER['REMOTE_ADDR'],
            'notify_url'        => config('alipay.callbackDomain').'/Supplier/Notice/wechatNativePayNotify',
            'trade_type'        => 'JSAPI',
            'openid'            => $openid
        ];
        // 获取签名
        $sign = self::MakeSign($data);
        $data['sign'] = $sign;
        //   dd($data);
        $xml = self::ToXml($data);
        //   dd($xml);
        // 提交获取数据
        $res = self::postXmlCurl($xml,$url,false);
        //   dd($res);
        $result = self::FromXml($res);

        $result['timeStamp']=time();
        $sign=array(
            'appId'=>config('wechat.appId'),
            'timeStamp'=>$result['timeStamp'],
            'nonceStr'=>$result['nonce_str'],
            'package'=>"prepay_id=".$result['prepay_id'],
            'signType'=>'MD5',
        );
        $result['paySign']=self::MakeSign($sign);
        return $result;

    }


    /**
     * native微信支付
     * @param $code
     * @return array
     */

    public static function nativeUnifiedorder($leaseId,$total_fee,$which_period,$order_no){
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $data = [
            'appid'             => config('wechat.appId'),
            'mch_id'            => config('wechat.mchId'),
            'nonce_str'         => md5(uniqid()),
            'sign_type'         => 'MD5',
            'body'              =>  '第'.$which_period.'期部分还款',  //商品描述
            'attach'            => $leaseId,
            'out_trade_no'      => $order_no,//订单号
            'fee_type'          => 'CNY',
            'total_fee'         => bcmul($total_fee,100),  //总金额
            'spbill_create_ip'  => $_SERVER['REMOTE_ADDR'],
            'notify_url'        => config('alipay.callbackDomain').'/Supplier/Notice/wechatNativePayNotify',
            'trade_type'        => 'NATIVE',
        ];
        // 获取签名
        $sign = self::MakeSign($data);
        $data['sign'] = $sign;
        //   dd($data);
        $xml = self::ToXml($data);
        //   dd($xml);
        // 提交获取数据
        $res = self::postXmlCurl($xml,$url,false);
        //   dd($res);
        $result = self::FromXml($res);
        return $result;
    }

    /**
     * 微信支付退款
     * @param $code
     * @return array
     */
    public static function refund($trade_no,$out_trade_no,$total_fee,$transpayAmout){
        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
        $data = [
            'appid'  => config('wechat.appId'),
            'mch_id' => config('wechat.mchId'),
            'nonce_str'=> md5(uniqid()), //随机串
            'sign'  => 'MD5',          //签名方式
            'transaction_id'=> $out_trade_no,//微信支付订单号 与商户订单号二选一
//            'out_trade_no'=> $out_trade_no, //商户订单号 和微信支付订单号二选一
            'out_refund_no' => $trade_no.time(),//退单号
            'total_fee'     => $transpayAmout,    //订单金额
            'refund_fee'    => $total_fee    //退款金额
        ];
        // 获取签名
       $sign = self::MakeSign($data);
       $data['sign'] = $sign;
    //   dd($data);
       $xml = self::ToXml($data);
    //   dd($xml);
       // 提交获取数据
       $res = self::postXmlCurl($xml,$url,true);
    //   dd($res);
       $result = self::FromXml($res);
       return $result;
    }

    public static function MakeSign($data)
    {
        //签名步骤一：按字典序排序参数
        ksort($data);
        $string = self::ToUrlParams($data);
        //$string = http_build_query($data);
        //签名步骤二：在string后加入KEY
        $string = $string . "&key=".config('wechat.key');
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    public static function ToXml($array){
        if(!is_array($array)|| count($array) <= 0){
           return ;
        }
        $xml = '<xml>';
        foreach ($array as $key=>$val){
            if (is_numeric($val)){
              $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }

    public static function FromXml($xml)
    {
        if(!$xml){
            return "xml数据异常！";
        }
        //将XML转为array
        //禁止引用外部xml实体
       libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $values;

    }
    /**
       * 以post方式提交xml到对应的接口url
       *
       * @param string $xml  需要post的xml数据
       * @param string $url  url
       * @param bool $useCert 是否需要证书，默认不需要
       * @param int $second   url执行超时时间，默认30s
       * @throws WxPayException
       */
     public static function postXmlCurl($xml, $url, $useCert = false, $second = 30)
     {
         $header = [
             'Content-type: application/json;'
         ];
         $curl = curl_init();
         curl_setopt($curl, CURLOPT_URL, $url);
         curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
         curl_setopt($curl, CURLOPT_HEADER, false);
         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
         curl_setopt($curl, CURLOPT_POST, TRUE);
         curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
         if($useCert == true){
             //设置证书
             //使用证书：cert 与 key 分别属于两个.pem文件
             curl_setopt($curl,CURLOPT_SSLCERTTYPE,'PEM');
             curl_setopt($curl,CURLOPT_SSLCERT,'/www/wwwroot/api.qianbaozuji.com/public/cert/apiclient_cert.pem');
             curl_setopt($curl,CURLOPT_SSLKEYTYPE,'PEM');
             curl_setopt($curl,CURLOPT_SSLKEY, '/www/wwwroot/api.qianbaozuji.com/public/cert/apiclient_key.pem');
         }
         $result = curl_exec($curl);

         curl_close($curl);
         return $result;
     }



    public static function ToUrlParams($array)
    {
        $buff = "";
        foreach ($array as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }

    public static function notices()
    {
        file_put_contents('./pay.txt',file_get_contents('php://input'),FILE_APPEND);
        $xml=file_get_contents('php://input');
        $data=self::FromXml($xml);
        return $data;
    }



    /**
     * 获取accessToken
     * @return array
     */
    public static function getQyAccessToken(){
        $data =  [];
        $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ww04d65953bde12aa8&corpsecret=wn4Ds7E1U5QPuOnxLED4tEsMhe355MPgQ7PPeNLDvfU";
        $param = [];
        $result = http_get($url,$param);
        $result = json_decode($result,true);
        if (isset($result['errcode'])&&$result['errcode']) {
            $flag =  false;
        }else{
            $flag =  true;
            $data = $result;
        }
        return ['status'=>$flag, 'message'=>$flag ? '成功' : '失败','data'=>$data];
    }

    /**
     * 获取资金流水
     * @param $code
     * @return array
     */
    public static function getFundFlow($transaction_id,$rent,$num=0,$next_cursor='',$total_fee=0){
        $data =  [];
        $accessToken = self::getQyAccessToken();
        $url = 'https://qyapi.weixin.qq.com/cgi-bin/externalpay/get_bill_list?access_token='.$accessToken['data']['access_token'];
        $param = [
            'begin_time'=>strtotime('-30 day')-86400*30*$num,
            'end_time'=>time()-86400*30*$num,
            'limit'=>1000,
            'cursor'=>$next_cursor
        ];
        $result = http_post($url,json_encode($param),['Content-type: application/json;charset=UTF-8']);
        $result = json_decode($result,true);


        if($num>6){
            return false;
        }
        self::requestLog('获取资金流水',['code'=>time()],$result);
        if (isset($result['errcode'])&&$result['errcode']) {
            return false;
        }else{
            $data = $result;
            $fund_flow_list=$data['bill_list'];
            $renta=$rent;
            $rent=bcmul($rent,100);
            $transaction_ida=$transaction_id;
            $transaction_id=explode(',',$transaction_id);
            $i=0;
            $total_fee=$total_fee;
            foreach ($transaction_id as $ka=>$va){

                if(strlen($va)>=32&&substr($va,0,4)==date('Y')){
                    $alipay=AlipayService::AlipayDataBillSellQueryRequest($va);
                    if($alipay){
                        foreach ($alipay as $k=>$v){
                            if($v['direction']=='收入'){
                                $i++;
                                $total_fee+=bcmul($v['trans_amount'],100);
                            }
                        }
                    }
                }else{
                    foreach ($fund_flow_list as $k=>$v){
                        if($v['transaction_id']==$va&&$v['trade_state']=='1'){
                            $i++;
                            $total_fee+=$v['total_fee'];
                        }
                    }
                }

            }

            if($i==count($transaction_id)&&$total_fee>=$rent&&$total_fee<bcadd($rent,10000)){
                return true;
            }else{
                if($result['next_cursor']){
                    self::getFundFlow($transaction_ida,$renta,$num,$result['next_cursor'],$total_fee);
                }
                return self::getFundFlow($transaction_ida,$renta,$num+1,$total_fee);
            }

        }
    }



    /**
     * 获取资金流水
     * @param $code
     * @return array
     */
    public static function getFundFlowOne($transaction_id,$num=0,$next_cursor=''){
        $data =  [];
        $accessToken = self::getQyAccessToken();
        $url = 'https://qyapi.weixin.qq.com/cgi-bin/externalpay/get_bill_list?access_token='.$accessToken['data']['access_token'];
        $param = [
            'begin_time'=>strtotime('-30 day')-86400*30*$num,
            'end_time'=>time()-86400*30*$num,
            'limit'=>1000,
            'cursor'=>$next_cursor
        ];
        $result = http_post($url,json_encode($param),['Content-type: application/json;charset=UTF-8']);
        $result = json_decode($result,true);


        if($num>15){
            return false;
        }
//        var_dump($result);
        self::requestLog('获取资金流水',['code'=>time()],$result);
        if (isset($result['errcode'])&&$result['errcode']) {
            return false;
        }else{
            $data = $result;
            $fund_flow_list=$data['bill_list'];
            $total_fee=0;
            if(strlen($transaction_id)>=28&&(substr($transaction_id,0,4)==date('Y')||substr($transaction_id,0,4)=='2024')){
                $alipay=AlipayService::AlipayDataBillSellQueryRequest($transaction_id);
                if($alipay){
                    foreach ($alipay as $k=>$v){
                        if($v['direction']=='收入'){
                            $total_fee+=bcmul($v['trans_amount'],100);
                        }
                    }
                }
            }else{
                foreach ($fund_flow_list as $k=>$v){
                    if($v['transaction_id']==$transaction_id&&$v['trade_state']=='1'){
                        $total_fee=$v['total_fee'];
                    }
                }
            }
            if($total_fee){
                return bcmul($total_fee,0.01,2);
            }else{
                if($result['next_cursor']){
                    return    self::getFundFlowOne($transaction_id,$num,$result['next_cursor']);
                }
                return  self::getFundFlowOne($transaction_id,$num+1);
            }

        }
    }

}
